module ysyx_22040213_div(
	input clk,
	input rst,
	input div_valid,
	input flush,
//	input divw,
	input [1:0] div_signed,
	input [63:0] dividend,
	input [63:0] divisor,
	output div_ready,
	output reg out_valid,
	output reg [63:0] quotient,
	output reg [63:0] remainder,
	output [63:0] diff_quo,
	output [63:0] diff_rem

);
`define YSYX_040053_XLEN 64
`define YSYX_040053_XXLEN 128
wire signed [63:0] s_dend = dividend;
wire signed [63:0] s_sor = divisor;
assign diff_quo = div_signed == 2'b11 ? s_dend / s_sor : dividend / divisor;
assign diff_rem = div_signed == 2'b11 ? s_dend % s_sor : dividend % divisor;


/* verilator lint_off UNUSED */

`define IDLE    2'b00
`define DIVING  2'b01
`define END     2'b10

reg [127:0] div_dend;
reg [63:0]  div_sor;
reg [63:0]  div_quo;
wire [64:0]  div_rem;
reg [64:0] rem;
reg [5:0] div_times;
reg [1:0] div_state;
wire quo_neg;
wire rem_neg;
wire [63:0] dividend_abs;
wire [63:0] divisor_abs;

assign div_ready = div_state == `IDLE;
assign div_rem = (div_dend[127:63] - {{1'b0},{div_sor}}); 
assign quo_neg = &div_signed & ~(dividend[63] & divisor[63]) & (dividend[63] || divisor[63]);
//assign quo_neg = &div_signed & (dividend[63] & divisor[63]);
assign rem_neg = &div_signed & dividend[63];
assign dividend_abs = ~dividend + `YSYX_040053_XLEN'b1;
assign divisor_abs  = ~divisor  + `YSYX_040053_XLEN'b1;


wire [64:0] dend = div_dend[127:63];
wire [64:0] sor  = {{1'b0},{div_sor}};

always @(posedge clk)begin
  if(rst || flush)begin
    div_dend <= 128'b0;
    div_sor <= 64'b0;
    div_quo <= 64'b0;
    div_times <= 6'b111111;
    div_state <= `IDLE;
    rem <= 65'b0;
  end else begin
    case(div_state)
      `IDLE: begin
        if(div_valid)begin
	  div_state <= `DIVING;
	  out_valid <= 1'b0;
//	  div_dend <= {{64'b0},{dividend}};
//	  div_sor <= divisor;
          div_dend <= &div_signed & dividend[`YSYX_040053_XLEN - 1] ? {`YSYX_040053_XLEN'b0, dividend_abs} : {`YSYX_040053_XLEN'b0, dividend};
          div_sor  <= &div_signed & divisor[`YSYX_040053_XLEN - 1]  ? divisor_abs : divisor;

	  div_times <= 6'b111111;
	end else begin
	  div_state <= `IDLE;
	  out_valid <= 1'b0;
	end
      end
      `DIVING: begin
	if(div_times != 0)begin
	  div_times <= div_times - 1;
	  div_quo[div_times] <= div_rem[64] ? 1'b0 : 1'b1;
	  div_dend <=  div_rem[64] ? {div_dend[126:0],{1'b0}} : {{div_rem[63:0]},{div_dend[62:0]},{1'b0}}; 
        end else begin
	  div_quo[div_times] <= div_rem[64] ? 1'b0 : 1'b1;
	  rem <= div_rem[64] ? div_rem + {{1'b0},{div_sor}} : div_rem;
	  div_state <= `END;
	end
      end
      `END: begin
	remainder <= (rem[64] & ~rem_neg) || (~rem[64] & rem_neg) ? ~rem[63:0] + 1 : rem[63:0];
	quotient  <= (div_quo[63] & ~quo_neg) || (~div_quo[63] & quo_neg) ? ~div_quo[63:0] + 1 : div_quo;
	out_valid <= 1'b1;
	div_state <= `IDLE;
      end
      default: div_state <= `IDLE;
    endcase
  end
end

/*
reg running_r;
    reg ready_r, valid_r;
    reg [6:0] cnt;
    reg [`YSYX_040053_XXLEN - 1:0] udividend_r;
    reg [`YSYX_040053_XLEN - 1:0] udivisor_r, quotient_r, remainder_r;
    reg dividend_s, divisor_s;
    wire [`YSYX_040053_XLEN - 1:0] dividend_abs, divisor_abs;
    wire [`YSYX_040053_XLEN - 1 : 0] sub;
    wire sub_s;

//abs
    assign dividend_abs = ~dividend + `YSYX_040053_XLEN'b1;
    assign divisor_abs  = ~divisor  + `YSYX_040053_XLEN'b1;

//status
    wire ready_to_doing = ready_r && div_valid;//握手成功，准备开始doing
    wire done_to_ready  = valid_r;//算完结果，准备拉高ready
    wire calculate_done = running_r && cnt == 7'h40;
    always @(posedge clk) begin
        if(rst || flush  || done_to_ready) begin
            ready_r <= 1'b1;
        end
        else if(ready_to_doing) begin
            ready_r <= 1'b0;
        end 
    end

    always @(posedge clk) begin
        if(rst || flush || calculate_done ) begin
            running_r <= 1'b0;
        end
        else if(ready_to_doing) begin
            running_r <= 1'b1;
        end 
    end

    always @(posedge clk) begin
        if(rst || flush || done_to_ready ) begin
            valid_r <= 1'b0;
        end
        else if(calculate_done) begin
            valid_r <= 1'b1;
        end 
    end

//sign
    always @(posedge clk)begin
        if(rst || flush) begin
            dividend_s <= 1'b0;
            divisor_s  <= 1'b0;
        end
        else if(ready_to_doing) begin
            dividend_s <= &div_signed & dividend[`YSYX_040053_XLEN - 1];
            divisor_s  <= &div_signed & divisor[`YSYX_040053_XLEN - 1];
        end
    end

//cnt
    always @(posedge clk) begin
        if(rst || flush || done_to_ready) begin
            cnt <= 7'b0;
        end
        else if(running_r) begin
            cnt <= cnt + 1'b1;
        end
    end

//calculate
    always @(posedge clk) begin
        if(rst) begin
            udividend_r <= 0;
            udivisor_r <= 0;
        end
        else if(ready_to_doing) begin
            udividend_r <= &div_signed & dividend[`YSYX_040053_XLEN - 1] ? {`YSYX_040053_XLEN'b0, dividend_abs} : {`YSYX_040053_XLEN'b0, dividend};
            udivisor_r  <= &div_signed & divisor[`YSYX_040053_XLEN - 1]  ? divisor_abs : divisor;
        end
        else if(running_r) begin
            udividend_r <= sub_s ? {udividend_r[`YSYX_040053_XXLEN - 2 : 0],1'b0} : {sub[`YSYX_040053_XLEN - 1:0], udividend_r[`YSYX_040053_XLEN - 2 : 0], 1'b0};
        end
    end 

    csa suber(.src1(udividend_r[`YSYX_040053_XXLEN - 1: `YSYX_040053_XLEN - 1]),
                      .src2({1'b1,~udivisor_r}),
                      .cin(1'b1),
                      .cout(sub_s),
                      .result(sub)
                      );

    always @(posedge clk) begin
        if(rst || flush || ready_to_doing) begin
            remainder_r <= `YSYX_040053_XLEN'b0;
            quotient_r  <= `YSYX_040053_XLEN'b0;
        end
        else if(calculate_done) begin
            remainder_r <= udividend_r[`YSYX_040053_XXLEN - 1: `YSYX_040053_XLEN]; 
            quotient_r  <= quotient_r;
        end
        else if(running_r) begin
            quotient_r <= {quotient_r[`YSYX_040053_XLEN - 2 : 0], ~sub_s};
        end 
    end
//correct result
    assign quotient = dividend_s ^ divisor_s ? ~quotient_r + `YSYX_040053_XLEN'b1 : quotient_r;
    assign remainder = dividend_s ? ~remainder_r + `YSYX_040053_XLEN'b1 : remainder_r;
   
    assign div_ready = ready_r;
    assign out_valid = valid_r;
*/
endmodule
